package com.z1.core.data;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.w3c.dom.Node;

import com.z1.core.xml.XMLParser;

public final class DataConfigLoader {

	private static final Logger logger = Logger.getLogger(DataConfigLoader.class);
	
	private static final String ENV_DATA_CONFIG_PARAM = "DATA_CONFIG";
	private static final String ENV_DATA_CONFIG_DEFAULT = "/dataConfig.xml";
	
	private static Map<String, DataConfig> dataConfigMap = new HashMap<String, DataConfig>(); 
	
	static {
		load();
	}
	
	private static void load() {
		try {
			dataConfigMap.clear();
			String dataConfigParam = System.getenv(ENV_DATA_CONFIG_PARAM);
			if (null == dataConfigParam || dataConfigParam.trim().equals("")) {
				dataConfigParam = ENV_DATA_CONFIG_DEFAULT;
			}
			InputStream input = DataConfigLoader.class.getResourceAsStream(dataConfigParam);
			if (null == input) { return; }
			XMLParser xmpParser = XMLParser.createXMLParser(input);
			Node root = xmpParser.getRootNode();
			loadDataConfigs(root);
		}
		catch (Throwable e) {
			logger.error("load dataConfig err", e);
		}
	}
	
	private static void loadDataConfigs(Node root) {
		List<Node> importNodes = XMLParser.getChildElementsByTag(root, "dataConfig");
		for (Node importNode : importNodes) {
			//ID
			String id = XMLParser.getElementAttr(importNode, "id");
			if (null == id) { continue;}
			//Bean
			String beanName = XMLParser.getElementAttr(importNode, "bean");
			Class<?> beanClass = null;
			try {
				if (null == beanName) { throw new Exception("dataConfig bean is not found."); }
				beanClass = Class.forName(beanName);
			}
			catch(Throwable e) {
				logger.error("load dataConfig(" + id + ") err", e);
				continue;
			}
			DataConfig dataConfig = new DataConfig()
				.id(id)
				.beanName(beanName)
				.beanClass(beanClass);
			
			//字段
			List<Node> cellNodes = XMLParser.getChildElementsByTag(importNode, "cell");
			for (Node cellNode : cellNodes) {
				//column
				String column = XMLParser.getElementAttr(cellNode, "column");
				if (null == column) { continue;}
				try {
					//property
					String property = XMLParser.getElementAttr(cellNode, "property");
					if (null == property) { throw new Exception("dataConfig cell property is not found."); }
					//comment
					String comment = XMLParser.getElementAttr(cellNode, "comment");
					if (null == comment) { throw new Exception("dataConfig cell comment is not found."); }
					//required
					String requiredStr = XMLParser.getElementAttr(cellNode, "required");
					Boolean required = 
						null != requiredStr && (
							requiredStr.equals("true") || 
							requiredStr.equals("required")
						) ? 
						true : 
						false;
					//javaType
					String javaType = XMLParser.getElementAttr(cellNode, "javaType");
					if (null == javaType) { throw new Exception("dataConfig cell javaType is not found."); }
					Class<?> javaTypeClass = Class.forName(javaType);
					//imports
					String importStr = XMLParser.getElementAttr(cellNode, "import");
					Boolean imports = null == importStr || importStr.equals("true") ? true : false;
					//export
					String exportStr = XMLParser.getElementAttr(cellNode, "export");
					Boolean export = null == exportStr || exportStr.equals("true") ? true : false;
					
					DataConfigCell cell = new DataConfigCell()
						.column(column)
						.property(property)
						.comment(comment)
						.required(required)
						.javaType(javaType)
						.javaTypeClass(javaTypeClass)
						.imports(imports)
						.export(export);
					
					//length
					String lengthStr = XMLParser.getElementAttr(cellNode, "length");
					if (null != lengthStr) {
						try { cell.setLength(Integer.parseInt(lengthStr)); }
						catch (Throwable ex) { }
					}
					//precision
					String precisionStr = XMLParser.getElementAttr(cellNode, "precision");
					if (null != lengthStr) {
						try { cell.setPrecision(Integer.parseInt(precisionStr)); }
						catch (Throwable ex) { }
					}
					
					dataConfig.addCell(cell);
				}
				catch (Throwable e) {
					logger.error("load dataConfig(" + id + ") cell(" + column + ") err", e);
				}
			}
			if (1 > dataConfig.getCells().size()) {
				logger.warn("load dataConfig(" + id + ") cells is 0");
			}
			else {
				dataConfigMap.put(dataConfig.getId(), dataConfig);
			}
		}
	}
	
	public static Map<String, DataConfig> getDataConfigMap() {
		return dataConfigMap;
	}
	
	public static DataConfig getDataConfig(String id) {
		return dataConfigMap.get(id);
	}
	
}
